home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / gfx / 3d / Skulpt_src.lha / sKulpt-src / Objects-Base.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-05  |  35.5 KB  |  1,263 lines

  1. #define STRICT
  2.  
  3. // Includes standard Windows
  4. #include <windows.h>
  5. #include <windowsx.h>
  6. #include <time.h>
  7. #include <stdlib.h>
  8. #include <malloc.h>
  9. #include <memory.h>
  10. #include <stdio.h>
  11.  
  12. // Includes D3D
  13. #define  D3D_OVERLOADS
  14. #include <ddraw.h>
  15. #include <d3d.h>
  16.  
  17. // Includes utilitaires D3D
  18. #include "d3dmath.h"
  19. #include "d3dutil.h"
  20. #include "D3DEnum.h"
  21.  
  22. #include <d3dx.h>
  23.  
  24. // Ids Resources
  25. //#include "resource.h"
  26.  
  27. // Constantes
  28. #include "const.h"
  29.  
  30. // Types
  31. #include "types.h"
  32.  
  33. // Variables globales projet
  34. #include "vars.h"
  35.  
  36. // Prototypes fonctions autres modules
  37. #include "proto.h"
  38.  
  39. // Macros
  40. #include "macros.h"
  41.  
  42. //************************************* C O M M U N S ***********************
  43. void vDeleteObjects(void)
  44. {
  45.     // RAZ points
  46.     for (int iVert = 0 ; iVert < XDC_NUMPT ; iVert++)
  47.     {
  48.         Vertices[iVert].bEnabled = FALSE;
  49.         Vertices[iVert].bHidden = FALSE;
  50.         Vertices[iVert].bSelected = FALSE;
  51.         Vertices[iVert].iDepend = 0;
  52.     }
  53.     iVertFirstAvailable = 0;
  54.     iVertLastUsed = -1;
  55.  
  56.     // RAZ arêtes
  57.     for (int iEdge = 0 ; iEdge < XDC_NUMEDGE ; iEdge++)
  58.     {
  59.         Edges[iEdge].bEnabled = FALSE;
  60.         Edges[iEdge].bHidden = FALSE;
  61.     }
  62.     iEdgeFirstAvailable = 0;
  63.     iEdgeLastUsed = -1;
  64.  
  65.     // RAZ lampes
  66.     for (int iLamp = 0 ; iLamp < XDC_NUMLAMP ; iLamp++)
  67.         if (Lampes[iLamp].bEnabled) bDeleteLamp(iLamp);
  68.  
  69.     iLampFirstAvailable = 0;
  70.     iLampLastUsed = iLampHilit = -1;
  71.  
  72.     // RAZ facettes
  73.     for (int iTriangle = 0 ; iTriangle < XDC_NUMTRI ; iTriangle++)
  74.     {
  75.         Triangles[iTriangle].bEnabled = FALSE;
  76.         Triangles[iTriangle].bHidden = FALSE;
  77.     }
  78.     iTriaFirstAvailable = 0;
  79.     iTriaLastUsed = iTriaHilit = -1;
  80.  
  81.     // RAZ matériaux
  82.     for (int iMtrl = 0 ; iMtrl < XDC_NUMMTRL ; iMtrl++)
  83.     {
  84.         Materials[iMtrl].bEnabled = FALSE;
  85.         Materials[iMtrl].bTextured = FALSE;
  86.         Materials[iMtrl].iTexture = 0;
  87.     }
  88.     iMtrlFirstAvailable = 0;
  89.     iMtrlLastUsed = -1;
  90.  
  91.     iFastMaterial("Blanc",    255,  255,  255);
  92.     iFastMaterial("Noir",       0,    0,    0);
  93.     iFastMaterial("Rouge",    255,    0,    0);
  94.     iFastMaterial("Vert",       0,  255,    0);
  95.     iFastMaterial("Bleu",       0,    0,  255);
  96.  
  97. #ifndef _AMIGA_
  98.     // RAZ Objets D3D
  99.     vDeleteD3DObjects();
  100. #endif
  101. }
  102.  
  103. //************************************** M A T E R I A L S *************************
  104. BOOL bSameMaterial(D3DMATERIAL7 *hMtrl1, D3DMATERIAL7 *hMtrl2)
  105. {
  106.     double fDist =
  107.                     fabs(hMtrl2 -> ambient.a - hMtrl1 -> ambient.a) +
  108.                     fabs(hMtrl2 -> ambient.r - hMtrl1 -> ambient.r) +
  109.                     fabs(hMtrl2 -> ambient.g - hMtrl1 -> ambient.g) +
  110.                     fabs(hMtrl2 -> ambient.b - hMtrl1 -> ambient.b) +
  111.  
  112.                     fabs(hMtrl2 -> diffuse.a - hMtrl1 -> diffuse.a) +
  113.                     fabs(hMtrl2 -> diffuse.r - hMtrl1 -> diffuse.r) +
  114.                     fabs(hMtrl2 -> diffuse.g - hMtrl1 -> diffuse.g) +
  115.                     fabs(hMtrl2 -> diffuse.b - hMtrl1 -> diffuse.b) +
  116.  
  117.                     fabs(hMtrl2 -> specular.a - hMtrl1 -> specular.a) +
  118.                     fabs(hMtrl2 -> specular.r - hMtrl1 -> specular.r) +
  119.                     fabs(hMtrl2 -> specular.g - hMtrl1 -> specular.g) +
  120.                     fabs(hMtrl2 -> specular.b - hMtrl1 -> specular.b) +
  121.                     fabs(hMtrl2 -> power - hMtrl1 -> power);
  122.  
  123.     return (fDist < 0.1);
  124. }
  125.  
  126. int iFindMaterial(D3DMATERIAL7 *hMtrl, int iPrevious)
  127. {
  128.     int iCnt;
  129.     float fTolerance = (float) fabs(fXmax - fXmin) / XDC_ZONE;
  130.     
  131.     // Rechercher le matériau
  132.     for (iCnt = max(iPrevious + 1, 0) ;
  133.             (iCnt <= iMtrlLastUsed)
  134.          && (!(   (Materials[iCnt].bEnabled == TRUE)
  135.                && (!bSameMaterial(hMtrl, &(Materials[iCnt].mtrl)))
  136.               ))
  137.          ;
  138.          iCnt++) ;
  139.  
  140.     // Si matériau trouvé alors renvoyer son indice
  141.     if (iCnt <= iMtrlLastUsed)
  142.         return(iCnt);
  143.  
  144.     // Sinon renvoyer -1
  145.     return -1;
  146. }
  147.  
  148. int iFastMaterial(char *sName, unsigned char bRouge, unsigned char bVert, unsigned char bBleu)
  149. {
  150.     D3DMATERIAL7 Mtrl, *pMtrl = &Mtrl;
  151.     ZeroMemory(pMtrl, sizeof(D3DMATERIAL7));
  152.     pMtrl -> ambient.a = 0.8f;
  153.     pMtrl -> ambient.r = (float) bRouge / 256.f / 6.f;
  154.     pMtrl -> ambient.g = (float) bVert / 256.f / 6.f;
  155.     pMtrl -> ambient.b = (float) bBleu / 256.f / 6.f;
  156.  
  157.     pMtrl -> diffuse.a = 0.8f;
  158.     pMtrl -> diffuse.r = (float) bRouge / 256.f;
  159.     pMtrl -> diffuse.g = (float) bVert / 256.f;
  160.     pMtrl -> diffuse.b = (float) bBleu / 256.f;
  161.  
  162.     pMtrl -> specular.a = 0.8f;
  163.     pMtrl -> specular.r = 1.f;
  164.     pMtrl -> specular.g = 1.f;
  165.     pMtrl -> specular.b = 1.f;
  166.     pMtrl -> power = 1.f;
  167.  
  168.     return iMakeMaterial(pMtrl, sName, XDC_ALLOWSAME);
  169. }
  170.  
  171. int iMakeMaterial(D3DMATERIAL7 *hMtrl, char *sName, BOOL bSame)
  172. {
  173.     int iCnt;
  174.     
  175.     // Rechercher le premier index libre
  176.     for (iCnt = bSame ? 0 : iMtrlFirstAvailable ;
  177.             (iCnt <= iMtrlLastUsed)
  178.          && (   ((!bSame) && (Materials[iCnt].bEnabled == TRUE))
  179.              || ((bSame) && (!(       (Materials[iCnt].bEnabled == TRUE) 
  180.                                 && (bSameMaterial(hMtrl, &(Materials[iCnt].mtrl)))
  181.                 )            ) )
  182.             ) ;
  183.          iCnt++) ;
  184.  
  185.     // Si limite tableau atteinte alors renvoyer erreur
  186.     if (iCnt >= XDC_NUMMTRL)
  187.     {
  188.         vTrace("*** E0016 : Plus de slots matériaux libres");
  189.         return -1;
  190.     }
  191.  
  192.     // Si matériau trouvé dans tableau alors le renvoyer
  193.     if (bSame)
  194.     {
  195.         if ((iCnt < XDC_NUMMTRL) && (Materials[iCnt].bEnabled == TRUE) 
  196.                                  && (bSameMaterial(hMtrl, &(Materials[iCnt].mtrl))))
  197.             return(iCnt);
  198.         else
  199.             return(iMakeMaterial(hMtrl, sName, XDC_FORCENEW));
  200.     }
  201.  
  202.     // Créer un nouveau material
  203.     Materials[iCnt].mtrl = *hMtrl;
  204.     if (sName) strcpy(Materials[iCnt].sName, sName); else strcpy(Materials[iCnt].sName, "[unnamed]");
  205.     Materials[iCnt].bEnabled = TRUE;
  206.     Materials[iCnt].bTextured = FALSE;
  207.     Materials[iCnt].sTexName[0] = 0;
  208.  
  209.     while (Materials[iMtrlFirstAvailable].bEnabled == TRUE) iMtrlFirstAvailable++;
  210.     if (iMtrlLastUsed < iCnt) iMtrlLastUsed = iCnt;
  211.  
  212.     return iCnt;
  213. }
  214.  
  215.  
  216. BOOL bDeleteMaterial(int iMtrl)
  217. {
  218.     // Si le material n'est pas enabled alors ne rien faire
  219.     if (Materials[iMtrl].bEnabled == FALSE) return FALSE;
  220.  
  221.     // Disabler le point
  222.     Materials[iMtrl].bEnabled = FALSE;
  223.     
  224.     // Mettre à jour les indices globaux du tableau des vertices
  225.     if (iMtrl == iMtrlLastUsed) while ((iMtrlLastUsed > -1) && (!Materials[--iMtrlLastUsed].bEnabled)) ;
  226.     if (iMtrl < iMtrlFirstAvailable) iMtrlFirstAvailable = iMtrl;
  227.  
  228.     return TRUE;
  229. }
  230.  
  231. //************************************** V E R T E X *************************
  232. int iFindVertex(D3DVECTOR p, int iPrevious)
  233. {
  234.     int iCnt;
  235.     float fTolerance = (float) fabs(fXmax - fXmin) / XDC_ZONE;
  236.     
  237.     // Rechercher le point
  238.     for (iCnt = max(iPrevious + 1, 0) ;
  239.             (iCnt <= iVertLastUsed)
  240.          && (!(   (Vertices[iCnt].bEnabled == TRUE)
  241.                && (Vertices[iCnt].bHidden == FALSE)
  242.                && (fabs(Vertices[iCnt].vPoint.x - p.x) < fTolerance)
  243.                && (fabs(Vertices[iCnt].vPoint.y - p.y) < fTolerance)
  244.                && (fabs(Vertices[iCnt].vPoint.z - p.z) < fTolerance)
  245.               ))
  246.          ;
  247.          iCnt++) ;
  248.  
  249.     // Si point trouvé alors renvoyer son indice
  250.     if (iCnt <= iVertLastUsed)
  251.         return(iCnt);
  252.  
  253.     // Sinon renvoyer -1
  254.     return -1;
  255. }
  256.  
  257. int iMakeVertex(D3DVECTOR p, BOOL bSame)
  258. {
  259.     int iCnt;
  260.     
  261.     // Rechercher le premier index libre
  262.     for (iCnt = bSame ? 0 : iVertFirstAvailable ;
  263.             (iCnt <= iVertLastUsed)
  264.          && (   ((!bSame) && (Vertices[iCnt].bEnabled == TRUE))
  265.              || ((bSame) && (!((Vertices[iCnt].bEnabled == TRUE) && (Vertices[iCnt].bHidden == FALSE) && (Magnitude(Vertices[iCnt].vPoint - p) < 10.f * g_EPSILON))))
  266.             ) ;
  267.          iCnt++) ;
  268.  
  269.     // Si limite tableau atteinte alors renvoyer erreur
  270.     if (iCnt >= XDC_NUMPT)
  271.     {
  272.         vTrace("*** E0016 : Plus de slots vertex libres");
  273.         return -1;
  274.     }
  275.  
  276.     // Si point trouvé dans tableau alors le renvoyer
  277.     if (bSame)
  278.     {
  279.         if ((iCnt < XDC_NUMPT) && (Vertices[iCnt].bEnabled == TRUE) && (Vertices[iCnt].bHidden == FALSE) && (Magnitude(Vertices[iCnt].vPoint - p) < 10.f * g_EPSILON))
  280.             return(iCnt);
  281.         else
  282.             return(iMakeVertex(p, XDC_FORCENEW));
  283.     }
  284.  
  285.     // Créer un nouveau point
  286.     Vertices[iCnt].vPoint = p;
  287.     Vertices[iCnt].bSelected = FALSE;
  288.     Vertices[iCnt].bHidden = FALSE;
  289.     Vertices[iCnt].bEnabled  =TRUE;
  290.  
  291.     while (Vertices[iVertFirstAvailable].bEnabled == TRUE) iVertFirstAvailable++;
  292.     if (iVertLastUsed < iCnt) iVertLastUsed = iCnt;
  293.  
  294.     return iCnt;
  295. }
  296.  
  297. BOOL bVertInEdge(int iVert, int iEdge)
  298. {
  299.     if (    (Edges[iEdge].iSommets[0] == iVert)
  300.          || (Edges[iEdge].iSommets[1] == iVert)
  301.        )
  302.         return TRUE;
  303.     else
  304.         return FALSE;
  305. }
  306.  
  307. BOOL bVertInTriangle(int iVert, int iTriangle)
  308. {
  309.     if (    (Triangles[iTriangle].iSommets[0] == iVert)
  310.          || (Triangles[iTriangle].iSommets[1] == iVert)
  311.          || (Triangles[iTriangle].iSommets[2] == iVert)
  312.        )
  313.         return TRUE;
  314.     else
  315.         return FALSE;
  316. }
  317.  
  318. int iEdgesPerVert(int iVert)
  319. {
  320.     int iCnt, jCnt = 0;
  321.  
  322.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  323.         if (bVertInEdge(iVert, iCnt))
  324.             jCnt++;
  325.  
  326.     return jCnt;
  327. }
  328.  
  329. int iTrianglesPerVert(int iVert)
  330. {
  331.     int iCnt, jCnt = 0;
  332.  
  333.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  334.         if (bVertInTriangle(iVert, iCnt))
  335.             jCnt++;
  336.  
  337.     return jCnt;
  338. }
  339.  
  340. BOOL bDeleteVertex(int iVert)
  341. {
  342.     int iCnt;
  343.  
  344.     // Si le point n'est pas enabled alors ne rien faire
  345.     if (Vertices[iVert].bEnabled == FALSE) return FALSE;
  346.  
  347.     // Disabler le point
  348.     Vertices[iVert].bEnabled = FALSE;
  349.     
  350.     // Mettre à jour les indices globaux du tableau des vertices
  351.     if (iVert == iVertLastUsed) while ((iVertLastUsed > -1) && (!Vertices[--iVertLastUsed].bEnabled)) ;
  352.     if (iVert < iVertFirstAvailable) iVertFirstAvailable = iVert;
  353.  
  354.     // Supprimer toutes les arêtes desquelles le sommet supprimé est une extrêmité
  355.     for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  356.         if (bVertInEdge(iVert, iCnt))
  357.             bDeleteEdge(iCnt);
  358.  
  359.     // Pour tout triangle duquel le sommet supprimé est un sommet, transformer le triangle en une arête entre les 2 sommets restants
  360.     for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  361.         if (bVertInTriangle(iVert, iCnt))
  362.         {
  363.             /*
  364.             if (Triangles[iCnt].iSommets[0] == iVert) iMakeEdge(Triangles[iCnt].iSommets[1], Triangles[iCnt].iSommets[2]);
  365.             if (Triangles[iCnt].iSommets[1] == iVert) iMakeEdge(Triangles[iCnt].iSommets[0], Triangles[iCnt].iSommets[2]);
  366.             if (Triangles[iCnt].iSommets[2] == iVert) iMakeEdge(Triangles[iCnt].iSommets[0], Triangles[iCnt].iSommets[1]);
  367.             */
  368.             bDeleteTriangle(iCnt);
  369.         }
  370.  
  371.     return TRUE;
  372. }
  373.  
  374. #ifndef _AMIGA_
  375. BOOL bSmoothNorm(int iVertex)
  376. {
  377.     if (Vertices[iVertex].bEnabled == FALSE) return FALSE;
  378.     if (Vertices[iVertex].bSmooth == FALSE) return FALSE;
  379.     if (Vertices[iVertex].iDepend == 0) return FALSE;
  380.  
  381.     D3DVECTOR vn = D3DVECTOR(0.f, 0.f, 0.f);
  382.  
  383.     for (int iTriangle = 0 ; iTriangle <= iTriaLastUsed ; iTriangle++)
  384.     {
  385.         if (Triangles[iTriangle].bEnabled == FALSE) continue;
  386.         if (!bVertInTriangle(iVertex, iTriangle)) continue;
  387.  
  388.         D3DVECTOR vc;
  389. /*
  390.         short iS0 = Triangles [iTriangle].iSommets[0],
  391.               iS1 = Triangles [iTriangle].iSommets[1],
  392.               iS2 = Triangles [iTriangle].iSommets[2];
  393.  
  394.         D3DVECTOR
  395.                 v01 = Vertices[iS1].vPoint - Vertices[iS0].vPoint,
  396.                 v02 = Vertices[iS2].vPoint - Vertices[iS0].vPoint,
  397.                 v12 = Vertices[iS2].vPoint - Vertices[iS1].vPoint,
  398.                 vn0, vn1, vn2;
  399.  
  400.         vn0 = Normalize(CrossProduct(v01, v02));
  401.         vn1 = Normalize(CrossProduct(v01, v12));
  402.         vn2 = Normalize(CrossProduct(v02, v12));
  403.  
  404. */
  405.         for (int iCnt = 0 ; iCnt < 3 ; iCnt++)
  406.             if (iVertex == Triangles [iTriangle].iSommets[iCnt])
  407.                 vc = D3DVECTOR(
  408.                     Triangles [iTriangle].pSommets[iCnt].nx,
  409.                     Triangles [iTriangle].pSommets[iCnt].ny,
  410.                     Triangles [iTriangle].pSommets[iCnt].nz);
  411.  
  412. /*
  413.         if (iVertex == iS0) vc = vn0;
  414.         if (iVertex == iS1) vc = vn1;
  415.         if (iVertex == iS2) vc = vn2;
  416.  
  417.         float fdp = DotProduct(vn, vc);
  418.  
  419.         if (fdp >= 0)
  420. */
  421.             vn += vc;
  422. /*
  423.         else
  424.             vn -= vc;
  425. */
  426.     }
  427.  
  428.     Vertices[iVertex].vNormal = Normalize(vn);
  429.  
  430.     return TRUE;
  431. }
  432. #endif
  433.  
  434. BOOL bIsVertexSelected(int iVertex)
  435. {
  436.     return
  437.         Vertices[iVertex].bEnabled && Vertices[iVertex].bSelected;
  438. }
  439.  
  440. //************************************** L A M P E S *************************
  441. int iFindLamp(D3DVECTOR p, int iPrevious)
  442. {
  443.     int iCnt;
  444.     float fTolerance = (float) fabs(fXmax - fXmin) / XDC_ZONE;
  445.     
  446.     // Rechercher la lampe
  447.     for (iCnt = max(iPrevious + 1, 0) ;
  448.             (iCnt <= iLampLastUsed)
  449.          && (!(   (Lampes[iCnt].bEnabled == TRUE)
  450.                && (fabs(Lampes[iCnt].lLamp.dvPosition.x - p.x) < fTolerance)
  451.                && (fabs(Lampes[iCnt].lLamp.dvPosition.y - p.y) < fTolerance)
  452.                && (fabs(Lampes[iCnt].lLamp.dvPosition.z - p.z) < fTolerance)
  453.               ))
  454.          ;
  455.          iCnt++) ;
  456.  
  457.     // Si point trouvé alors renvoyer son indice
  458.     if (iCnt <= iLampLastUsed)
  459.         return(iCnt);
  460.  
  461.     // Sinon renvoyer -1
  462.     return -1;
  463. }
  464.  
  465. int iMakeLamp(
  466.     D3DLIGHTTYPE    dltType,            /* Type of light source */
  467.     D3DCOLORVALUE   dcvDiffuse,         /* Diffuse color of light */
  468.     D3DCOLORVALUE   dcvSpecular,        /* Specular color of light */
  469.     D3DCOLORVALUE   dcvAmbient,         /* Ambient color of light */
  470.     D3DVECTOR       dvPosition,         /* Position in world space */
  471.     D3DVECTOR       dvDirection,        /* Direction in world space */
  472.     D3DVALUE        dvRange,            /* Cutoff range */
  473.     D3DVALUE        dvFalloff,          /* Falloff */
  474.     D3DVALUE        dvAttenuation0,     /* Constant attenuation */
  475.     D3DVALUE        dvAttenuation1,     /* Linear attenuation */
  476.     D3DVALUE        dvAttenuation2,     /* Quadratic attenuation */
  477.     D3DVALUE        dvTheta,            /* Inner angle of spotlight cone */
  478.     D3DVALUE        dvPhi               /* Outer angle of spotlight cone */
  479. )
  480. {
  481.     int iCnt;
  482.     
  483.     // Rechercher le premier index libre
  484.     for (iCnt = iLampFirstAvailable ;
  485.             (iCnt <= iLampLastUsed)
  486.          && (Lampes[iCnt].bEnabled == TRUE) ;
  487.          iCnt++) ;
  488.  
  489.     // Si limite tableau atteinte alors renvoyer erreur
  490.     if (iCnt >= XDC_NUMLAMP)
  491.     {
  492.         vTrace("*** E0017 : Plus de slots vertex libres");
  493.         return -1;
  494.     }
  495.  
  496.     // Créer une nouvelle lampe
  497.     ZeroMemory(&Lampes[iCnt].lLamp, sizeof(D3DLIGHT7));
  498.     Lampes[iCnt].bEnabled = TRUE;
  499.     Lampes[iCnt].bSelected = FALSE;
  500.     Lampes[iCnt].bLit = TRUE;
  501.     Lampes[iCnt].lLamp.dltType = dltType; // D3DLIGHT_POINT ou D3DLIGHT_DIRECTIONAL ou D3DLIGHT_SPOT
  502.     Lampes[iCnt].lLamp.dcvDiffuse = dcvDiffuse;
  503.     Lampes[iCnt].lLamp.dcvSpecular = dcvSpecular;
  504.     Lampes[iCnt].lLamp.dcvAmbient = dcvAmbient;
  505.     Lampes[iCnt].lLamp.dvPosition = dvPosition;
  506.     Lampes[iCnt].lLamp.dvDirection = dvDirection;
  507.     Lampes[iCnt].lLamp.dvRange = dvRange;
  508.     Lampes[iCnt].lLamp.dvFalloff = dvFalloff;
  509.     Lampes[iCnt].lLamp.dvAttenuation0 = dvAttenuation0; 
  510.     Lampes[iCnt].lLamp.dvAttenuation1 = dvAttenuation1; 
  511.     Lampes[iCnt].lLamp.dvAttenuation2 = dvAttenuation2; 
  512.     Lampes[iCnt].lLamp.dvTheta = dvTheta; 
  513.     Lampes[iCnt].lLamp.dvPhi = dvPhi; 
  514.  
  515. #ifndef NO3D
  516.     lpd3dDevice->SetLight(iCnt, &Lampes[iCnt].lLamp);
  517.     lpd3dDevice->LightEnable(iCnt, Lampes[iCnt].bLit);
  518. #endif
  519.  
  520.     while (Lampes[iLampFirstAvailable].bEnabled == TRUE) iLampFirstAvailable++;
  521.     if (iLampLastUsed < iCnt) iLampLastUsed = iCnt;
  522.  
  523.     return iCnt;
  524. }
  525.  
  526. BOOL bUpdateLamp(int iLamp)
  527. {
  528.     // Si la lampe n'est pas enabled alors ne rien faire
  529.     if (Lampes[iLamp].bEnabled == FALSE) return FALSE;
  530.  
  531. #ifndef NO3D
  532.     lpd3dDevice->SetLight(iLamp, &Lampes[iLamp].lLamp);
  533.     lpd3dDevice->LightEnable(iLamp, Lampes[iLamp].bLit);
  534. #endif
  535.  
  536.     return TRUE;
  537. }
  538.  
  539. BOOL bDeleteLamp(int iLamp)
  540. {
  541.     // Si la lampe n'est pas enabled alors ne rien faire
  542.     if (Lampes[iLamp].bEnabled == FALSE) return FALSE;
  543.  
  544.     // Disabler la lampe
  545. #ifndef NO3D
  546.     lpd3dDevice->LightEnable(iLamp, FALSE);
  547. #endif
  548.     Lampes[iLamp].bEnabled = FALSE;
  549.     Lampes[iLamp].bLit = FALSE;
  550.     
  551.     // Mettre à jour les indices globaux du tableau des lampes
  552.     if (iLamp == iLampLastUsed) while ((iLampLastUsed > -1) && (!Lampes[--iLampLastUsed].bEnabled)) ;
  553.     if (iLamp < iLampFirstAvailable) iLampFirstAvailable = iLamp;
  554.  
  555.     return TRUE;
  556. }
  557.  
  558. //************************************** E D G E S ***************************
  559. int iFindEdge(int i1, int i2)
  560. {
  561.     int iCnt;
  562.  
  563.     for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  564.         if (    ((Edges[iCnt].iSommets[0] == i1) || (Edges[iCnt].iSommets[1] == i1))
  565.              && ((Edges[iCnt].iSommets[0] == i2) || (Edges[iCnt].iSommets[1] == i2))
  566.            )
  567.            return iCnt;
  568.  
  569.     return -1;
  570. }
  571.  
  572. int iMakeEdge(int i1, int i2)
  573. {
  574.     int iCnt;
  575.  
  576.     // Rechercher un slot d'arête libre
  577.     for (iCnt = iEdgeFirstAvailable ; (iCnt <= iEdgeLastUsed) && (Edges [iCnt].bEnabled == TRUE) ; iCnt++);
  578.  
  579.     // Si pas trouvé alors fail
  580.     if (iCnt >= XDC_NUMEDGE)
  581.     {
  582.         vTrace("*** E0018 : Plus de slots arêtes libres");
  583.         return -1;
  584.     }
  585.  
  586.     // Créer l'arête
  587.     Edges [iCnt].iSommets[0] = i1;
  588.     Edges [iCnt].iSommets[1] = i2;
  589.  
  590.     Edges[iCnt].bEnabled = TRUE;
  591.     Edges[iCnt].bHidden = FALSE;
  592.  
  593.     while (Edges[iEdgeFirstAvailable].bEnabled == TRUE) iEdgeFirstAvailable++;
  594.     if (iEdgeLastUsed < iCnt) iEdgeLastUsed = iCnt;
  595.     
  596.     return iCnt;
  597. }
  598.  
  599. BOOL bDeleteEdge(int iEdge)
  600. {
  601.     // Si l'arête n'est pas enabled alors ne rien faire
  602.     if (Edges[iEdge].bEnabled == FALSE) return FALSE;
  603.  
  604.     // Disabler l'arête
  605.     Edges[iEdge].bEnabled = FALSE;
  606.     
  607.     // Mettre à jour les indices globaux du tableau des arêtes
  608.     if (iEdge == iEdgeLastUsed) while ((iEdgeLastUsed > -1) && !(Edges[--iEdgeLastUsed].bEnabled)) ;
  609.     if (iEdge < iEdgeFirstAvailable) iEdgeFirstAvailable = iEdge;
  610.  
  611.     return TRUE;
  612. }
  613.  
  614. BOOL    bIsEdgeSelected(int iEdge)
  615. {
  616.     return
  617.         Edges[iEdge].bEnabled &&
  618.         bIsVertexSelected(Edges[iEdge].iSommets[0]) &&
  619.         bIsVertexSelected(Edges[iEdge].iSommets[1]);
  620. }
  621.  
  622. BOOL    bIsEdgePartiallySelected(int iEdge)
  623. {
  624.     return 
  625.         Edges[iEdge].bEnabled &&
  626.         (bIsVertexSelected(Edges[iEdge].iSommets[0]) ||
  627.          bIsVertexSelected(Edges[iEdge].iSommets[1]));
  628. }
  629.  
  630. //************************************** T R I A N G L E S *******************
  631. int iFindTriangle(int i1, int i2, int i3)
  632. {
  633.     int iCnt;
  634.  
  635.     for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  636.         if (    ((Triangles[iCnt].iSommets[0] == i1) || (Triangles[iCnt].iSommets[1] == i1) || (Triangles[iCnt].iSommets[2] == i1))
  637.              && ((Triangles[iCnt].iSommets[0] == i2) || (Triangles[iCnt].iSommets[1] == i2) || (Triangles[iCnt].iSommets[2] == i2))
  638.              && ((Triangles[iCnt].iSommets[0] == i3) || (Triangles[iCnt].iSommets[1] == i3) || (Triangles[iCnt].iSommets[2] == i3))
  639.            )
  640.            return iCnt;
  641.  
  642.     return -1;
  643. }
  644.  
  645. BOOL bSetUV(int iTriangle, int u0, int v0, int u1, int v1, int u2, int v2)
  646. {
  647.     if (iTriangle > iTriaLastUsed) return FALSE;
  648.     if (!Triangles[iTriangle].bEnabled) return FALSE;
  649.  
  650.     Triangles[iTriangle].u[0] = u0;
  651.     Triangles[iTriangle].u[1] = u1;
  652.     Triangles[iTriangle].u[2] = u2;
  653.     Triangles[iTriangle].v[0] = v0;
  654.     Triangles[iTriangle].v[1] = v1;
  655.     Triangles[iTriangle].v[2] = v2;
  656.  
  657.     return TRUE;
  658. }
  659.  
  660. int iMakeTriangle(int i1, int i2, int i3, int iMtrl)
  661. {
  662.     int iCnt;
  663.  
  664.     // Rechercher un slot de triangle libre
  665.     for (iCnt = iTriaFirstAvailable ; (iCnt <= iTriaLastUsed) && (Triangles [iCnt].bEnabled == TRUE) ; iCnt++);
  666.  
  667.     // Si pas trouvé alors fail
  668.     if (iCnt >= XDC_NUMTRI)
  669.     {
  670.         vTrace("*** E0019 : Plus de slots triangles libres");
  671.         return -1;
  672.     }
  673.  
  674.     // Créer le triangle
  675.     Triangles [iCnt].iSommets[0] = i1;
  676.     Triangles [iCnt].iSommets[1] = i2;
  677.     Triangles [iCnt].iSommets[2] = i3;
  678.  
  679.     // Incrémenter le compteur de triangles des sommets
  680.     Vertices[Triangles [iCnt].iSommets[0]].iDepend++;
  681.     Vertices[Triangles [iCnt].iSommets[1]].iDepend++;
  682.     Vertices[Triangles [iCnt].iSommets[2]].iDepend++;
  683.  
  684.     // Affecter couleur et aspect
  685.     Triangles[iCnt].iMtrl = iMtrl;
  686.     Triangles[iCnt].bEnabled = TRUE;
  687.     Triangles[iCnt].bHidden = FALSE;
  688.  
  689. #ifndef _AMIGA_
  690.     // Mettre à jour les coordonnées du triangle D3D correspondant
  691.     bUpdateD3DTri(iCnt);
  692. #endif
  693.  
  694.     while (Triangles[iTriaFirstAvailable].bEnabled == TRUE) iTriaFirstAvailable++;
  695.     if (iTriaLastUsed < iCnt) iTriaLastUsed = iCnt;
  696.     
  697.     return iCnt;
  698. }
  699.  
  700. BOOL bDeleteTriangle(int iTriangle)
  701. {
  702.     // Si le triangle n'est pas enabled alors ne rien faire
  703.     if (Triangles[iTriangle].bEnabled == FALSE) return FALSE;
  704.  
  705.     // Disabler le triangle
  706.     Triangles[iTriangle].bEnabled = FALSE;
  707.     
  708.     // Mettre à jour les indices globaux du tableau des triangles
  709.     if (iTriangle == iTriaLastUsed) while ((iTriaLastUsed > -1) && (!Triangles[--iTriaLastUsed].bEnabled)) ;
  710.     if (iTriangle < iTriaFirstAvailable) iTriaFirstAvailable = iTriangle;
  711.  
  712.     // Décrémenter le compteur de triangles des sommets
  713.     Vertices[Triangles [iTriangle].iSommets[0]].iDepend--;
  714.     Vertices[Triangles [iTriangle].iSommets[1]].iDepend--;
  715.     Vertices[Triangles [iTriangle].iSommets[2]].iDepend--;
  716.  
  717.     return TRUE;
  718. }
  719.  
  720. #ifndef _AMIGA_
  721. BOOL bUpdateD3DTri(int iCnt)
  722. {
  723.     if (Triangles[iCnt].bEnabled == FALSE) return FALSE;
  724.     
  725.     short iS0 = Triangles [iCnt].iSommets[0],
  726.           iS1 = Triangles [iCnt].iSommets[1],
  727.           iS2 = Triangles [iCnt].iSommets[2];
  728.  
  729.     D3DVECTOR
  730.             v01 = Vertices[iS1].vPoint - Vertices[iS0].vPoint,
  731.             v02 = Vertices[iS2].vPoint - Vertices[iS0].vPoint,
  732.             v12 = Vertices[iS2].vPoint - Vertices[iS1].vPoint,
  733.             vn0, vn1, vn2,
  734.             v1, v2, vp2, v3, v4;
  735.     
  736.     D3DMATRIX p;
  737.  
  738.     // Calculer la normale au point 0 : v3
  739.     v1 = Normalize(v01);
  740.     v2 = Normalize(v02);
  741.     v3 = Normalize(CrossProduct(v01, v02));
  742.     
  743.     // On fait un repère orthonormal avec v3 et v1 (qui sont orthonormés) et leur produit vectoriel
  744.     vp2 = Normalize(CrossProduct(v3, v1));
  745.  
  746.     // On fait la matrice de changement de repère 
  747.     D3DUtil_SetIdentityMatrix(p);
  748.     p._11 = v1.x;
  749.     p._21 = v1.y;
  750.     p._31 = v1.z;
  751.     p._12 = vp2.x;
  752.     p._22 = vp2.y;
  753.     p._32 = vp2.z;
  754.     p._13 = v3.x;
  755.     p._23 = v3.y;
  756.     p._33 = v3.z;
  757.  
  758.     // on calcule l'image de z dans le nouveau repère : v4
  759.     D3DMath_VectorMatrixMultiply(v4, D3DVECTOR(0.f, 0.f, 1.f), p);
  760.  
  761.     // On vérifie que v4 est dans le même sens que z, ce qui nous dit si le triangle est CW ou CCW
  762.     float fSign = DotProduct(D3DVECTOR(0.f, 0.f, 1.f), v4);
  763.  
  764.     // On calcule les vecteurs normaux
  765.     if (Vertices[iS0].bSmooth) { bSmoothNorm(iS0); vn0 = Vertices[iS0].vNormal; }
  766.     else vn0 = Normalize(CrossProduct(v01, v02));
  767.  
  768.     if (Vertices[iS1].bSmooth) { bSmoothNorm(iS1); vn1 = Vertices[iS1].vNormal; }
  769.     else vn1 = Normalize(CrossProduct(v01, v12));
  770.  
  771.     if (Vertices[iS2].bSmooth) { bSmoothNorm(iS2); vn2 = Vertices[iS2].vNormal; }
  772.     else vn2 = Normalize(CrossProduct(v02, v12));
  773.  
  774.     // Créer les 2 triangles D3D (CW, CCW) en ordonnant les sommets pour avoir les CCW en 1er
  775.     if (fSign >= 0)
  776.     {
  777.         Triangles [iCnt].pSommets[0] = D3DVERTEX(Vertices[iS0].vPoint, vn0, 0, 0);
  778.         Triangles [iCnt].pSommets[1] = D3DVERTEX(Vertices[iS1].vPoint, vn1, 0, 0);
  779.         Triangles [iCnt].pSommets[2] = D3DVERTEX(Vertices[iS2].vPoint, vn2, 0, 0);
  780.         Triangles [iCnt].pSommets[3] = D3DVERTEX(Vertices[iS0].vPoint, -vn0, 0, 0);
  781.         Triangles [iCnt].pSommets[4] = D3DVERTEX(Vertices[iS2].vPoint, -vn2, 0, 0);
  782.         Triangles [iCnt].pSommets[5] = D3DVERTEX(Vertices[iS1].vPoint, -vn1, 0, 0);
  783.     }
  784.     else
  785.     {
  786.         Triangles [iCnt].pSommets[0] = D3DVERTEX(Vertices[iS0].vPoint, -vn0, 0, 0);
  787.         Triangles [iCnt].pSommets[1] = D3DVERTEX(Vertices[iS2].vPoint, -vn2, 0, 0);
  788.         Triangles [iCnt].pSommets[2] = D3DVERTEX(Vertices[iS1].vPoint, -vn1, 0, 0);
  789.         Triangles [iCnt].pSommets[3] = D3DVERTEX(Vertices[iS0].vPoint, vn0, 0, 0);
  790.         Triangles [iCnt].pSommets[4] = D3DVERTEX(Vertices[iS1].vPoint, vn1, 0, 0);
  791.         Triangles [iCnt].pSommets[5] = D3DVERTEX(Vertices[iS2].vPoint, vn2, 0, 0);
  792.     }
  793.  
  794.     return TRUE;
  795. }
  796. #endif
  797.  
  798. BOOL bSubdivideTriangle(int iTriangle)
  799. {
  800.     int iNewV[3], iNewT[4];
  801.     
  802.     if (Triangles[iTriangle].bEnabled == FALSE) return(FALSE);
  803.  
  804.     if (-1 == (iNewV[0] = iMakeVertex(
  805.                 (Vertices[Triangles[iTriangle].iSommets[0]].vPoint +
  806.                  Vertices[Triangles[iTriangle].iSommets[1]].vPoint
  807.                 ) / 2.f, XDC_ALLOWSAME))) return FALSE;
  808.  
  809.     if (-1 == (iNewV[1] = iMakeVertex(
  810.                 (Vertices[Triangles[iTriangle].iSommets[1]].vPoint +
  811.                  Vertices[Triangles[iTriangle].iSommets[2]].vPoint
  812.                 ) / 2.f, XDC_ALLOWSAME))) return FALSE;
  813.  
  814.     if (-1 == (iNewV[2] = iMakeVertex(
  815.                 (Vertices[Triangles[iTriangle].iSommets[2]].vPoint +
  816.                  Vertices[Triangles[iTriangle].iSommets[0]].vPoint
  817.                 ) / 2.f, XDC_ALLOWSAME))) return FALSE;
  818.  
  819.     if (-1 == (iNewT[0] = iMakeTriangle(iNewV[0], iNewV[1], iNewV[2], Triangles[iTriangle].iMtrl))) return FALSE;
  820.     if (-1 == (iNewT[1] = iMakeTriangle(iNewV[0], iNewV[1], Triangles[iTriangle].iSommets[1], Triangles[iTriangle].iMtrl))) return FALSE;
  821.     if (-1 == (iNewT[2] = iMakeTriangle(iNewV[1], iNewV[2], Triangles[iTriangle].iSommets[2], Triangles[iTriangle].iMtrl))) return FALSE;
  822.     if (-1 == (iNewT[3] = iMakeTriangle(iNewV[0], iNewV[2], Triangles[iTriangle].iSommets[0], Triangles[iTriangle].iMtrl))) return FALSE;
  823.  
  824.     Vertices[iNewV[0]].bSelected =
  825.     Vertices[iNewV[1]].bSelected =
  826.     Vertices[iNewV[2]].bSelected = Vertices[Triangles[iTriangle].iSommets[0]].bSelected;
  827.  
  828.     return bDeleteTriangle(iTriangle);
  829. }
  830.  
  831. BOOL    bIsTriangleSelected(int iTriangle)
  832. {
  833.     return
  834.         Triangles[iTriangle].bEnabled &&
  835.         bIsVertexSelected(Triangles[iTriangle].iSommets[0]) &&
  836.         bIsVertexSelected(Triangles[iTriangle].iSommets[1]) &&
  837.         bIsVertexSelected(Triangles[iTriangle].iSommets[2]);
  838. }
  839.  
  840. BOOL    bIsTrianglePartiallySelected(int iTriangle)
  841. {
  842.     return 
  843.         Triangles[iTriangle].bEnabled &&
  844.         (bIsVertexSelected(Triangles[iTriangle].iSommets[0]) ||
  845.          bIsVertexSelected(Triangles[iTriangle].iSommets[1]) ||
  846.          bIsVertexSelected(Triangles[iTriangle].iSommets[2]));
  847. }
  848.  
  849. //********************************************** O U T I L S *************************
  850. // Propager de façon **non** récursive la dé/sélection d'un vertex aux vertices connexes (à travers edges ou triangles)
  851. void vPropagateSelection(void)
  852. {
  853.     register BOOL bReste;
  854.  
  855.     bReste = TRUE;
  856.     while (bReste)
  857.     {
  858.         bReste = FALSE;
  859.  
  860.         for (register int iEdge = 0 ; iEdge <= iEdgeLastUsed ; iEdge++)
  861.             if (bIsEdgePartiallySelected(iEdge) && !bIsEdgeSelected(iEdge))
  862.                 bReste =
  863.                 Vertices[Edges[iEdge].iSommets[0]].bSelected = 
  864.                 Vertices[Edges[iEdge].iSommets[1]].bSelected = TRUE;
  865.     }
  866.  
  867.     bReste = TRUE;
  868.     while (bReste)
  869.     {
  870.         bReste = FALSE;
  871.  
  872.         for (register int iTria = 0 ; iTria <= iTriaLastUsed ; iTria++)
  873.             if (bIsTrianglePartiallySelected(iTria) && !bIsTriangleSelected(iTria))
  874.                 bReste =
  875.                 Vertices[Triangles[iTria].iSommets[0]].bSelected = 
  876.                 Vertices[Triangles[iTria].iSommets[1]].bSelected = 
  877.                 Vertices[Triangles[iTria].iSommets[2]].bSelected = TRUE;
  878.     }
  879. }
  880.  
  881. // Cloner la sélection
  882. BOOL bCloneSelection(D3DVECTOR vShift, BOOL bCloneMode)
  883. {
  884.     int iCnt, jCnt, iNumSelected, *iIndex;
  885.  
  886.     // Compter les points sélectionnés
  887.     iNumSelected = 0;
  888.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  889.         if (bIsVertexSelected(iCnt)) iNumSelected++;
  890.  
  891.     if (!iNumSelected) return FALSE;
  892.  
  893.     // Allouer la table de correspondance ancien / nouvel index
  894.     iIndex = (int *) malloc(iNumSelected * 2 * sizeof(int));
  895.  
  896.     // Cloner les points sélectionnés en conservant la table de correspondance ancien / nouveau
  897.     // et en décalant les nouveaux de vShift
  898.     jCnt = 0;
  899.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  900.     {
  901.         D3DVECTOR vVect = Vertices[iCnt].vPoint + vShift;
  902.  
  903.         if (!bIsVertexSelected(iCnt)) continue;
  904.  
  905.         // Remplir la table de correspondance ancien / nouveau
  906.         iIndex[jCnt] = iCnt;
  907.         iIndex[jCnt + 1] = iMakeVertex(vVect, XDC_FORCENEW);
  908.         jCnt += 2;
  909.     }
  910.  
  911.     // Cloner les arêtes éventuelles entre les anciens points
  912.     for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  913.     {
  914.         if (Edges[iCnt].bEnabled == FALSE) continue;
  915.  
  916.         int iOVert1 = Edges[iCnt].iSommets[0],
  917.             iOVert2 = Edges[iCnt].iSommets[1],
  918.             iCVert1 = -1,
  919.             iCVert2 = -1;
  920.  
  921.         // Vérifier que les deux sommets originaux de l'arête sont sélectionnés
  922.         if (bIsVertexSelected(iOVert1) && bIsVertexSelected(iOVert2))
  923.         {
  924.             // Alors il faut créer une nouvelle arête avec les sommets clonés
  925.             for (jCnt = 0 ; jCnt < iNumSelected ; jCnt++)
  926.             {
  927.                 if (iIndex[jCnt * 2] == iOVert1) iCVert1 = iIndex[jCnt * 2 + 1];
  928.                 if (iIndex[jCnt * 2] == iOVert2) iCVert2 = iIndex[jCnt * 2 + 1];
  929.             }
  930.             if ((iCVert1 != -1) && (iCVert2 != -1))
  931.             {
  932.                 iMakeEdge(iCVert1, iCVert2);
  933.  
  934.                 // Si le mode de clonage est avec extrusion, créer les triangles de l'élévation
  935.                 if (bCloneMode == XDC_MODE_EXTRUDE)
  936.                 {
  937.                     iMakeTriangle(iOVert1, iCVert1, iCVert2, 0);
  938.                     iMakeTriangle(iOVert1, iOVert2, iCVert2, 0);
  939.                 }
  940.             }
  941.         }
  942.     }
  943.  
  944.     // Cloner les triangles éventuels entre les différents points
  945.     for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  946.     {
  947.         if (Triangles[iCnt].bEnabled == FALSE) continue;
  948.  
  949.         int iOVert1 = Triangles[iCnt].iSommets[0],
  950.             iOVert2 = Triangles[iCnt].iSommets[1],
  951.             iOVert3 = Triangles[iCnt].iSommets[2],
  952.             iCVert1 = -1,
  953.             iCVert2 = -1,
  954.             iCVert3 = -1;
  955.  
  956.         // Vérifier que les trois sommets originaux du triangle sont sélectionnés
  957.         if (bIsVertexSelected(iOVert1) && bIsVertexSelected(iOVert2) && bIsVertexSelected(iOVert3))
  958.         {
  959.             // Alors il faut créer un nouveau triangle avec les sommets clonés
  960.             for (jCnt = 0 ; jCnt < iNumSelected ; jCnt++)
  961.             {
  962.                 if (iIndex[jCnt * 2] == iOVert1) iCVert1 = iIndex[jCnt * 2 + 1];
  963.                 if (iIndex[jCnt * 2] == iOVert2) iCVert2 = iIndex[jCnt * 2 + 1];
  964.                 if (iIndex[jCnt * 2] == iOVert3) iCVert3 = iIndex[jCnt * 2 + 1];
  965.             }
  966.             if ((iCVert1 != -1) && (iCVert2 != -1) && (iCVert3 != -1))
  967.             {
  968.                 int iNew = iMakeTriangle(iCVert1, iCVert2, iCVert3, Triangles[iCnt].iMtrl);
  969.                 for (int iIndex = 0 ; iIndex < 3 ; iIndex++)
  970.                 {
  971.                     Triangles[iNew].u[iIndex] = Triangles[iCnt].u[iIndex];
  972.                     Triangles[iNew].v[iIndex] = Triangles[iCnt].v[iIndex];
  973.                 }
  974.  
  975.                 // Si le mode de clonage est avec extrusion, créer les triangles de l'élévation
  976.                 if (bCloneMode == XDC_MODE_EXTRUDE)
  977.                 {
  978.                     iMakeTriangle(iOVert1, iCVert1, iCVert2, Triangles[iCnt].iMtrl);
  979.                     iMakeTriangle(iOVert1, iOVert2, iCVert2, Triangles[iCnt].iMtrl);
  980.                     iMakeTriangle(iOVert2, iCVert2, iCVert3, Triangles[iCnt].iMtrl);
  981.                     iMakeTriangle(iOVert2, iOVert3, iCVert3, Triangles[iCnt].iMtrl);
  982.                     iMakeTriangle(iOVert1, iCVert1, iCVert3, Triangles[iCnt].iMtrl);
  983.                     iMakeTriangle(iOVert1, iOVert3, iCVert3, Triangles[iCnt].iMtrl);
  984.                 }
  985.             }
  986.         }
  987.     }
  988.  
  989.     // Inverser la sélection (sélectionner les nouveaux points)
  990.     for (iCnt = 0 ; iCnt < iNumSelected ; iCnt++)
  991.     {
  992.         Vertices[iIndex[iCnt * 2    ]].bSelected = FALSE;
  993.         Vertices[iIndex[iCnt * 2 + 1]].bSelected = TRUE;
  994.     }
  995.  
  996.     // Libérer la table de correspondance
  997.     free(iIndex);
  998.  
  999.     return TRUE;
  1000. }
  1001.  
  1002. // Cacher les éléments de la sélection
  1003. void vHideSelection(void)
  1004. {
  1005.     int iVert, iCnt;
  1006.  
  1007.     for (iVert = 0 ; iVert <= iVertLastUsed ; iVert++)
  1008.     {
  1009.         if (bIsVertexSelected(iVert))
  1010.         {
  1011.             Vertices[iVert].bHidden = TRUE;
  1012.             Vertices[iVert].bSelected = FALSE;
  1013.  
  1014.             for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  1015.             {
  1016.                 if (Edges[iCnt].bEnabled == FALSE) continue;
  1017.  
  1018.                 if (bVertInEdge(iVert, iCnt))
  1019.                     Edges[iCnt].bHidden = TRUE;
  1020.             }
  1021.             for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  1022.             {
  1023.                 if (Triangles[iCnt].bEnabled == FALSE) continue;
  1024.  
  1025.                 if (bVertInTriangle(iVert, iCnt))
  1026.                     Triangles[iCnt].bHidden = TRUE;
  1027.             }
  1028.         }
  1029.     }
  1030. }
  1031.  
  1032. // Rendre visibles les éléments cachés
  1033. void vRevealHidden(void)
  1034. {
  1035.     int iCnt;
  1036.  
  1037.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  1038.     {
  1039.         if (Vertices[iCnt].bEnabled == FALSE) continue;
  1040.  
  1041.         Vertices[iCnt].bHidden = FALSE;
  1042.     }
  1043.  
  1044.     for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  1045.     {
  1046.         if (Edges[iCnt].bEnabled == FALSE) continue;
  1047.  
  1048.         Edges[iCnt].bHidden = FALSE;
  1049.     }
  1050.  
  1051.     for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  1052.     {
  1053.         if (Triangles[iCnt].bEnabled == FALSE) continue;
  1054.  
  1055.         Triangles[iCnt].bHidden = FALSE;
  1056.     }
  1057. }
  1058.  
  1059. // Déterminer le barycentre de la sélection
  1060. D3DVECTOR vCenter(void)
  1061. {
  1062.     D3DVECTOR dVect = D3DVECTOR(0.f, 0.f, 0.f);
  1063.     int jCnt = 0;
  1064.  
  1065.     for (int iVert = 0 ; iVert <= iVertLastUsed ; iVert++)
  1066.         if (bIsVertexSelected(iVert))
  1067.         {
  1068.             // Mémoriser les coordonnées avant modification
  1069.             Vertices[iVert].vPointBack = Vertices[iVert].vPoint;
  1070.             
  1071.             // Compter les points
  1072.             jCnt++;
  1073.  
  1074.             // Additionner les coordonnées du point à celles du barycentre
  1075.             dVect.x += Vertices[iVert].vPoint.x;
  1076.             dVect.y += Vertices[iVert].vPoint.y;
  1077.             dVect.z += Vertices[iVert].vPoint.z;
  1078.         }
  1079.  
  1080.     if (!jCnt) 
  1081.     {
  1082.         vTrace("*** E0022 : Pas de sélection");
  1083.         return dVect;
  1084.     }
  1085.  
  1086.     // Moyenner la somme des points
  1087.     dVect.x /= jCnt;
  1088.     dVect.y /= jCnt;
  1089.     dVect.z /= jCnt;
  1090.  
  1091.     return dVect;
  1092. }
  1093.  
  1094. // Garbage collektor !-)
  1095. void vCollect(void)
  1096. {
  1097.     int iShift, iVert, iMtrl, *iMapTo;
  1098.  
  1099.     // Réindexer les arêtes
  1100.     iShift = 0;
  1101.  
  1102.     for (int iEdge = 0 ; iEdge <= iEdgeLastUsed ; iEdge++)
  1103.     {
  1104.         if (Edges[iEdge].bEnabled == FALSE)
  1105.         {
  1106.             while (Edges[iEdge + iShift].bEnabled == FALSE)
  1107.             {
  1108.                 iShift++;
  1109.                 iEdgeLastUsed--;
  1110.             }
  1111.         }
  1112.         if (iShift)
  1113.         {
  1114.             Edges[iEdge] = Edges[iEdge + iShift];
  1115.             Edges[iEdge + iShift].bEnabled = FALSE;
  1116.         }
  1117.     }
  1118.  
  1119.     iEdgeFirstAvailable = iEdgeLastUsed + 1;
  1120.  
  1121.     // Réindexer les triangles
  1122.     iShift = 0;
  1123.  
  1124.     for (int iTria = 0 ; iTria <= iTriaLastUsed ; iTria++)
  1125.     {
  1126.         if (Triangles[iTria].bEnabled == FALSE)
  1127.         {
  1128.             while (Triangles[iTria + iShift].bEnabled == FALSE)
  1129.             {
  1130.                 iShift++;
  1131.                 iTriaLastUsed--;
  1132.             }
  1133.         }
  1134.         if (iShift)
  1135.         {
  1136.             Triangles[iTria] = Triangles[iTria + iShift];
  1137.             Triangles[iTria + iShift].bEnabled = FALSE;
  1138.         }
  1139.     }
  1140.  
  1141.     iTriaFirstAvailable = iTriaLastUsed + 1;
  1142.  
  1143.     // Compter les sommets inutilisés pour ne faire la suite que s'il y en a
  1144.     iShift = 0;
  1145.  
  1146.     for (iVert = 0 ; iVert <= iVertLastUsed ; iVert++)
  1147.         if (Vertices[iVert].bEnabled == FALSE)
  1148.             iShift++;
  1149.  
  1150.     if (!iShift)
  1151.         goto _DoneVert;
  1152.  
  1153.     // Allouer la table de mapping
  1154.     if (!(iMapTo = (int *) malloc((iVertLastUsed + 1) * sizeof(int))))
  1155.     {
  1156.         vTrace("*** E0032 : erreur malloc table mapping GC");
  1157.         return;
  1158.     }
  1159.  
  1160.     // Préinitialiser la table de mapping
  1161.     for (iShift = 0 ; iShift <= iVertLastUsed ; iShift++)
  1162.         iMapTo[iShift] = iShift;
  1163.  
  1164.     // Réindexer les sommets
  1165.     iShift = 0;
  1166.  
  1167.     for (iVert = 0 ; iVert <= iVertLastUsed ; iVert++)
  1168.     {
  1169.         if (Vertices[iVert].bEnabled == FALSE)
  1170.         {
  1171.             while (Vertices[iVert + iShift].bEnabled == FALSE)
  1172.             {
  1173.                 iShift++;
  1174.                 iVertLastUsed--;
  1175.             }
  1176.         }
  1177.  
  1178.         if (iShift)
  1179.         {
  1180.             Vertices[iVert] = Vertices[iVert + iShift];
  1181.             Vertices[iVert + iShift].bEnabled = Vertices[iVert + iShift].bSelected = FALSE;
  1182.             iMapTo[iVert + iShift] = iVert;
  1183.         }
  1184.     }
  1185.  
  1186.     iVertFirstAvailable = iVertLastUsed + 1;
  1187.  
  1188.     // Réindexer les sommets dans les arêtes
  1189.     for(iShift = 0 ; iShift <= iEdgeLastUsed ; iShift++)
  1190.     {
  1191.         Edges[iShift].iSommets[0] = iMapTo[Edges[iShift].iSommets[0]];
  1192.         Edges[iShift].iSommets[1] = iMapTo[Edges[iShift].iSommets[1]];
  1193.     }
  1194.  
  1195.     // Réindexer les sommets dans les triangles
  1196.     for(iShift = 0 ; iShift <= iTriaLastUsed ; iShift++)
  1197.     {
  1198.         Triangles[iShift].iSommets[0] = iMapTo[Triangles[iShift].iSommets[0]];
  1199.         Triangles[iShift].iSommets[1] = iMapTo[Triangles[iShift].iSommets[1]];
  1200.         Triangles[iShift].iSommets[2] = iMapTo[Triangles[iShift].iSommets[2]];
  1201.     }
  1202.  
  1203.     // Libérer la table
  1204.     free(iMapTo);
  1205.  
  1206. _DoneVert:
  1207.  
  1208.     // Compter les matériaux inutilisés pour ne faire la suite que s'il y en a
  1209.     iShift = 0;
  1210.  
  1211.     for (iMtrl = 0 ; iMtrl <= iMtrlLastUsed ; iMtrl++)
  1212.         if (Materials[iMtrl].bEnabled == FALSE)
  1213.             iShift++;
  1214.  
  1215.     if (!iShift)
  1216.         return;
  1217.  
  1218.     // Allouer la table de mapping
  1219.     if (!(iMapTo = (int *) malloc((iMtrlLastUsed + 1) * sizeof(int))))
  1220.     {
  1221.         vTrace("*** E0032 : erreur malloc table mapping GC");
  1222.         return;
  1223.     }
  1224.  
  1225.     // Préinitialiser la table de mapping
  1226.     for (iShift = 0 ; iShift <= iMtrlLastUsed ; iShift++)
  1227.         iMapTo[iShift] = iShift;
  1228.  
  1229.     // Réindexer les matériaux
  1230.     iShift = 0;
  1231.  
  1232.     for (iMtrl = 0 ; iMtrl <= iMtrlLastUsed ; iMtrl++)
  1233.     {
  1234.         if (Materials[iMtrl].bEnabled == FALSE)
  1235.         {
  1236.             while (Materials[iMtrl + iShift].bEnabled == FALSE)
  1237.             {
  1238.                 iShift++;
  1239.                 iMtrlLastUsed--;
  1240.             }
  1241.         }
  1242.  
  1243.         if (iShift)
  1244.         {
  1245.             Materials[iMtrl] = Materials[iMtrl + iShift];
  1246.             Materials[iMtrl + iShift].bEnabled = FALSE;
  1247.             iMapTo[iMtrl + iShift] = iMtrl;
  1248.         }
  1249.     }
  1250.  
  1251.     iMtrlFirstAvailable = iMtrlLastUsed + 1;
  1252.  
  1253.     // Réindexer les matériaux dans les triangles
  1254.     for(iShift = 0 ; iShift <= iTriaLastUsed ; iShift++)
  1255.         Triangles[iShift].iMtrl = iMapTo[Triangles[iShift].iMtrl];
  1256.  
  1257.     // Libérer la table
  1258.     free(iMapTo);
  1259.  
  1260.     // Réindexer matériaux <-> textures
  1261.     vXRefMaterials2Textures();
  1262. }
  1263.